﻿/****************************************************************************************
 * Name         :   Image processing filters
 * Author       :   Shah-nawaj Shuhan
 * Description  :   This file is part of Onuprova 3D camera. It impliments some filters
 *                  to generate stereoscopic image.
 * Company      :   Onuprova
 * URL          :   http://onuprova.com
 * 
 * Reference    :   Information from http://en.wikipedia.org/wiki/Anaglyph_image
 *                  has been used to generate the filter configuration.
 ****************************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Drawing.Imaging;

namespace _3D_Processor.ImageProcessor
{
    /// <summary>
    /// Enumarate the colour schemes
    /// </summary>
    public enum ColourScheme
    {
        RedGreen = 0,
        RedBlue = 1,
        RedCyan = 2,
        GreenMagenta = 3,
        MagentaCyan = 4
    }

    /// <summary>
    /// Configuration for colour filter
    /// </summary>
    public class ColourFilterConfiguration
    {
        /// <summary>
        /// Percentage of red channel
        /// </summary>
        public float Red{get;set;}
        /// <summary>
        /// Percentage of green channel
        /// </summary>
        public float Green { get; set; }
        /// <summary>
        /// Percentage of blue channel
        /// </summary>
        public float Blue { get; set; }

        /// <summary>
        /// Create a new instance of colour filter configuration
        /// </summary>
        /// <param name="Red">Percentage of red (0-100)</param>
        /// <param name="Green">Percentage of green (0-100)</param>
        /// <param name="Blue">Percentage of blue (0-100)</param>
        public ColourFilterConfiguration(float Red, float Green, float Blue)
        {
            if (Red > 1 || Green > 1 || Blue > 1 || Red < 0 || Green < 0 || Blue < 0) throw (new Exception("Red green and Blue must be between 0-1"));
            this.Red = Red;
            this.Green = Green;
            this.Blue = Blue;
        }

    }

    /// <summary>
    /// Contains some filtering function for image processing
    /// </summary>
    public class ImageProcessor
    {

        public static Bitmap GetAnaglyph(Bitmap LeftImage, ColourFilterConfiguration LeftFilter, Bitmap RightImage, ColourFilterConfiguration RightFilter)
        {
            if (LeftImage.Width != RightImage.Width || LeftImage.Height != RightImage.Height)
            {
                throw new Exception("Left and Right images should have same width and height");
            }
            if (LeftFilter.Red + RightFilter.Red > 1 || LeftFilter.Green + RightFilter.Green > 1 || LeftFilter.Blue + RightFilter.Blue > 1)
            {
                throw new Exception("Filter parameter has been conflicted. Summation each colour percentages in the Left and Right filter should be less equal 1. Which means LeftFilter.Red + RightFilter.Red <= 1. It also applies for Green and Blue channels");
            }

            UnsafeBitmap OutputBitmap = new UnsafeBitmap(LeftImage.Width, LeftImage.Height);
            UnsafeBitmap LeftUnsafe = new UnsafeBitmap(LeftImage);
            UnsafeBitmap RightUnsafe = new UnsafeBitmap(RightImage);
            OutputBitmap.LockBitmap();
            LeftUnsafe.LockBitmap();
            RightUnsafe.LockBitmap();

            for (int w = 0; w < LeftImage.Width; w++)
            {
                for (int h = 0; h < RightImage.Height; h++)
                {
                    Pixel LeftPixel = LeftUnsafe.GetPixel(w, h);
                    Pixel RightPixel = RightUnsafe.GetPixel(w, h);
                    //Calculate Red
                    byte Red = (byte)((float)RightPixel.red * RightFilter.Red + ((float)LeftPixel.red * LeftFilter.Red));
                    //Calculate Green
                    byte Green = (byte)((float)RightPixel.green * RightFilter.Green + ((float)LeftPixel.green * LeftFilter.Green));
                    //Calculate Blue
                    byte Blue = (byte)((float)RightPixel.blue * RightFilter.Blue + ((float)LeftPixel.blue * LeftFilter.Blue));
                    //Set Pixel
                    OutputBitmap.SetPixel(w, h, new Pixel(Red, Green, Blue));
                }
            }

            OutputBitmap.UnlockBitmap();
            LeftUnsafe.UnlockBitmap();
            RightUnsafe.UnlockBitmap();

            return OutputBitmap.Bitmap;
        }
        
    }

}
